#include "core/state/BlackboardStateRunning.h"
#include "network/packet/Packets.h"
#include <QDebug>

BlackboardStateRunning * BlackboardStateRunning::instancePtr = NULL;

BlackboardState * BlackboardStateRunning::instance() {
    if (instancePtr == NULL) {
        instancePtr = new BlackboardStateRunning();
    }
    return instancePtr;
}

void BlackboardStateRunning::packetReceived(BlackboardManager * manager, AbstractPacket * packet) {
    switch (packet->getPacketType()) {
    case JOIN_REQUEST:
    {
        if (joiningNode != NULL) {
            BusyPacket busyPacket;
            manager->sendPacket(&busyPacket);
            return;
        }

        JoinRequestPacket *joinRequetstPacket = (JoinRequestPacket *) packet;
        QString senderId        = joinRequetstPacket->getSenderId();
        QString senderAddress   = joinRequetstPacket->getSenderAddress();
        quint16 senderPort      = joinRequetstPacket->getSenderPort();
        QColor penColor         = joinRequetstPacket->getPenColor();

        joiningNode = new Node(senderId, senderAddress, senderPort, penColor);

        JoinResponsePacket joinResponse(manager->getNodeListModel()->innerList(),
                                        manager->getWidth(), manager->getHeight(),
                                        manager->getCurrentBlackboardImage());
        joinResponse.setReceiver(senderAddress, senderPort);
        manager->sendPacket(&joinResponse);

        JoinInfoPacket joinInfo(*joiningNode, manager->getThisNode());
        joinInfo.setReceiver(&manager->getNextNode());
        manager->sendPacket(&joinInfo);
    }
    break;
    case JOIN_INFO:
    {
        JoinInfoPacket *joinInfoPacket = (JoinInfoPacket *) packet;
        Node * prevNode = joinInfoPacket->getPrevJoinNode();
        Node * joinNode = joinInfoPacket->getJoinNode();
        const Node & nextNode = manager->getNextNode();
        manager->getNodeListModel()->addNode(*prevNode, *joinNode);

        if (joiningNode != NULL && *joiningNode == *joinNode) {
            packet->setReceiver(joiningNode);
            manager->sendPacket(packet);

            delete joiningNode;
            joiningNode = NULL;
        } else {
            joinInfoPacket->setReceiver(&nextNode);
            manager->sendPacket(joinInfoPacket);
        }
    }
    break;
    case PAINT:
        manager->processAndSendPaintPacket((PaintPacket *) packet);
        break;
    case MUTUAL_EXCL_TOKEN:
        manager->processMutualExclusionTokenPacket((MutualExclusionTokenPacket *) packet);
        break;
    default:
        qWarning() << "Unimplemented case in BlackboardStateRunning::packetReceived";
    }
}
